Web2Py を使ってみよう
Web2Py について
Web2pyは、オープンソースで開発されているスケーラブルなデータベース駆動型WebアプリケーションのためのフルスタックWebフレームワークです。
Web2pyはもともと、使いやすさに重点を置いた教育ツールとして提供されていたため、シンプルでプロジェクトレベルの設定ファイル(例:Django の settinngs.py)を用意する必要がありません。
Web2Py の設計思想は次の3つに集約されます。
簡単に使えること
web2py はフルスタック・フレームワークで、開発に必要なもの(データベース、Webサーバ、WebベースIDE、API、ライブラリーなど)が全てが含まれています。
不足する機能はプラグインとして追加することができるようになっています。
Web2Pyでは開発をフレームワーク内で完結することができるため、導入後すぐ開発することができます。フレームワークから独立した機能はないので学習コストは低くなります。
例えば データベース抽象化レイヤ(DAL:Database Abstraction Layer)は、データベースを抽象化するもので、MySQL、Oracle といったデータベースの差異によらず、同じ知識と技術で開発を行うことができるようになります。
速く開発できること
web2py ではすべての機能についてデフォルト値を持っています。Django では 設定ファイル、URLディスパッチャ、テンプレート、ハンドラなど必要になる設定を定義をしないとWebアプリケーションとしては動作しません。これに対して、web2py では定義していない設定はデフォルト値をとるため一部分をコードするだけでもWebアプリケーションとして動作することができます。
例えば、コントローラに関数を追加するだけで、自動的にデフォルトのテンプレートとURLが割り当てられます。
セキュリティの確保がされていること
web2py はセキュリティ確保に注力されています。クロスサイトスクリプティング や SQLインジェクション といったWebアプリケーションに対する脅威にデフォルトで対応する仕組みがあります。
Web2py機能の重要なものをあげておきます。
インストールや設定で必要な外部モジュールが不要
プラットフォームに応じたZIPファイルを1つを展開して実行するだけ
Pythonも含まれているので事前にインストールするがありません
プラットフォーム依存がない
Windows、Mac、Linux / Unix、Google App Engine、Amazon EC2
PythonまたはJythonのいずれかをサポートするWebホスティングで実行可能
複数プロトコルに対応
HTML/XML, REST, ATOM, RSS, RTF, CSV, JSON, JSON-RPC, XML-RPC, AMF-RPC, SOAP
脆弱性を防ぐデータ・セキュリティ
クロスサイトスクリプティング、インジェクション、悪意のあるファイルの実行の防止
チケットシステム
エラーが発生するたびにチケットを発行しデバッグを簡単にする仕組み
コードの読み取りと保守を容易にするエラー追跡、完全なエラーログ
ユーザーはエラーとそのステータスを追跡することが簡単になる
役割ベースのアクセス制御
国際化のサポート
旧バージョンとの下位互換性の担保
AJAX、JQuery、CSSフレームワーク、JavaScriptフレームワークのサポート
JOB実行(cron実装)
コードのバージョン管理
WebIDEで保存されているスナップショットまたはひとつ前のバージョンに戻れる
mercurial がインストールされていればWebIDEからバージョン管理が行える
インストール
web2pyはシステム領域へインストールする必要がありません。これはサーバの管理者権限(root権限)が不要ということです。オフィシャルサイトから利用するプラットフォーム用のZIPファイルをダウンロードして解凍したあと、適切な web2py ファイルを実行するだけで動作させることができます。
https://gyazo.com/f611e86a4dd6a0dabf1555edacbbd6f8
ソースコードからの起動
PyPIでリリースされているバージョンは Python3 との互換性がよくありません。
Web2Pyを利用する場合は次のようにGitHubのリポジトリから入手するか、オフィシャルサイトからパッケージをダウンロードしてください。
code: bash
$ cd web2py
$ git submodule update --init --recursive
$ python web2py.py
Web2Pyの起動
web2pyにはWindowsとMac OS X用のバイナリパッケージが提供されています。これにはPythonも含まれているので、公開用のサーバへPythonをインストールすることも不要です。
また、Windows、Mac、Linux、その他のUnixシステムで動作するソースコードも公開されています。ソースコードパッケージは、Pythonが既にコンピュータにインストールされていることを前提としています。
それぞれのパッケージでは、次のようにweb2pyを実行します。
code: UnixおよびLinux(ソースコード配布)
python web2py.py
code: OSX Macバイナリ配布
open web2py.app
code: Windows バイナリweb2py配布
web2py.exe
code: Windows ソースweb2py配布
python.exe web2py.py
Web2Py を起動すると、デフォルトではGUIウィジェットが表示され、一度限りの管理パスワード、WebサーバーのネットワークインターフェイスのIPアドレス、リクエストを受けるポート番号の入力が求められます。
https://gyazo.com/bd136f701bc08b34f265fa1a0f3a9075
デフォルトでは、web2pyはhttp://127.0.0.1:8000にアクセスすることになりますが、任意のIPアドレスとポートでも動作させることもできます。
任意のIPアドレスで動作させているサーバ上でweb2pyを動作させて公開するような時は、0.0.0.0:80 を使用してください。
https://gyazo.com/cf11effc9b7ed05a05f6b4dafb12f8fe
https://gyazo.com/20512f7150e7680c9f394c9130e47137
ここで、新規アプリケーションとして "myapp" を作成すると次の管理画面になります。
https://gyazo.com/6fc871b81e312ebab5f2cdc35b94583f
このアプリケーションにはhttp://127.0.0.1:8000/myapp でアクセスします。
あとは、このオンラインエディタ(WebベースIDE)を通して開発を進めてゆくことになります。
Web2Py のファイル構成
web2pyはDjangoやFlaskとは異なりRails と同じようなMVCモデルを採用しています。
このため、WebPyによるアプリケーションは次のファイル群から構成されます。
モデル(Model)
アプリケーションによって保存されたデータの説明を含むファイル。
たとえば、データベースのテーブルのフィールド、それらの関係や要件を定義します。
web2pyは、各モデルファイルで定義されているテーブルを示します。
コントローラー(Controler)
アプリケーションのロジックを含むファイル。
各URLはコントローラーファイル内の関数に一意にマッピングされます。
この関数は、ページをレンダリングするビューを呼び出します。
web2pyは、各コントローラーファイルによって公開される関数を通知します。
ビュー(View)
アプリケーションのプレゼンテーション層です。
Django や Flask ではテンプレートと呼ばれるファイル群で、コントローラによって返される変数を、HTMLでレンダリングされる特別な{{ }}タグを含むファイルです。
web2pyは、ビューが他のビューを継承やインポートしたときに通知します。
言語(Languages)
国際化のためのすべての文字列の変換テーブルを含むファイル
静的ファイル(Static files)
画像、CSS、JavaScriptなど、その他すべてのファイル。
モジュール
アプリケーションで利用するモジュールファイル
プライベートファイル(Private files)
公開しない内部ファイル
プラグイン
機能拡張のためのファイル
Web2Py でのURLマッピング
https://gyazo.com/102fc81b79ec81cf007d92baf653524b
web2pyのアプリケーションは、モデル、ビュー、コントローラーを使用します。
他のフレームワークが採用しているMVCモデルとは少し異なり、web2pyのモデルは条件付きとして扱われます。 コントローラの使用状況に基づいて、サブディレクトリにあるモデルが実行されます。
いま、URLとして次のようにアクセスされたとします。
http://127.0.0.1:8000/app/cont/func.html
この場合、appはアプリケーションの名前、contはコントローラーの名前、funcはコントローラーに関連付けられた関数やモジュール名となります。
この場合、次のモデルのファイルが実行されます。
applications/app/models/*.py
applications/app/models/cont/*.py
applications/app/models/cont/func/*.py
ビュー
Django Template や Jinja2 と同様に Web2Py のビューはテンプレートエンジンが使えます。
Web2Pyで使用されているテンプレートエンジンはYATLパッケージとして独立していて単独で使用することもできます。
デリミタ{{ }}` に囲まれた中にPythonコードを埋め込むことができ、ビューコードに展開されたあと、最終的にHTMLにレンダリングされます。
いま、次のようなビューがあるとします。
code: HTML
{{=x}}
これは次のようなビューコードに展開されます。
code: Python
response.write(x)
この方法でオブジェクト x がビューに渡されます。
もう少し複雑な例を見てみましょう。
code: HTML
<html><body>
{{for x in range(10):}}{{=x}}hello<br />{{pass}}
</body></html>
これは、次のビューコードに展開されます。
code: Python
response.write("""<html><body>""", escape=False)
for x in range(10):
response.write(x)
response.write("""hello<br />""", escape=False)
response.write("""</body></html>""", escape=False)
ビューの記述にエラーがあるときは、エラーレポートには開発者が記述したビューではなく、生成されたビューコードが表示されます。これは、開発時にデバッグするときに便利です。
ビューで使用されるテンプレート言語YATLはHTMLのルールで記述されるPythonコードとなります。このためデリミタ{{ }} の中ではPythonのインデントルールは無視されます。Pythonは通常、コードブロックを区切るためにインデントを使用するのですが、それが使えないので、コードブロックの終端として {{ pass }} を記述します。
for ... in
要素を繰り返すようなときは for を使います。
code: HTML
<ul>
{{for item in items:}}<li>{{=item}}</li>{{pass}}
</ul>
これは次のようにレンダリングされます。
code: HTML
<ul>
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
while
条件が成り立つ間繰り返したいときは while を使います。
code: HTML
{{k = 3}}
<ul>
{{while k > 0:}}<li>{{=k}}{{k = k - 1}}</li>{{pass}}
</ul>
code: HTML
<ul>
<li>3</li>
<li>2</li>
<li>1</li>
</ul>
if ... elif ... else
code: HTML
{{
import random
k = random.randint(0, 100)
}}
<h2>
{{=k}}
{{if k % 2:}}is odd{{else:}}is even{{pass}}
</h2>
{{ if }} の終端は {{ pass }} となることに注意してください。
code: HTML
<h2>
45 is odd
</h2>
try ... except ... else ... finally
これは強力です。テンプレート言語で try文が使えます。
code: HTML
{{try:}}
Hello {{= 1 / 0}}
{{except:}}
division by zero
{{else:}}
no division by zero
{{finally:}}
<br />
{{pass}}
code: HTML
Hello division by zero
<br />
def ... return
Pythonの関数を定義することだってできてしまいます。
code: HTML
{{def itemize1(link): return LI(A(link, _href="http://" + link))}} <ul>
{{=itemize1('www.google.com')}}
</ul>
code: HTML
<ul>
<li><a href="http:/www.google.com">www.google.com</a></li>
</ul>
フォーム
web2pyにはフォーム生成のための強力な関数が提供されています。
次の4つの方法でフォームを構築することができます。
FORM
HTMLヘルパーを使うときは低レベルの実装となります。
FORMオブジェクトは、そのフィールドのデータ内容を保持しています。
SQLFORM
既存のデータベースに対して作成、更新、削除の機能を提供します。
SQLFORM.factory
SQLFORMとよく似たフォームを生成しますが、SQLFORMの上位にある抽象化レイヤーとなります。ここでは、新しいデータベースを作成する必要はありません。
CRUDメソッド
CURDの名前が示すように、SQLFORMの機能を備えた作成(create)、取得(read)、更新(update)、および削除(delete)機能を提供します。
FORM
コントローラ default.py に次のモデルが割り当てられているとします。
code: Python
def display_form():
return dict()
これに関連するビューは次のようになります。
この例では、HTMLヘルパーを使ってフォームを実装しています。
code: Python
{{extend 'layout.html'}}
<h2>Basic Form</h2>
<form enctype = "multipart/form-data"
action = "{{= URL()}}" method = "post">
Your name:
<input name = "name" />
<input type = "submit" />
</form>
<h2>Submitted variables</h2>
{{= BEAUTIFY(request.vars)}}
FORMを使うと次のように簡潔に記述できます。
コントローラは次のように記述します。
code: python
def display_form():
form = FORM('Value:',
INPUT(_value = 'name'), INPUT(_type = 'submit'))
return dict(form = form)
ビューは次のようになります。
code: Python
{{extend 'layout.html'}}
<h2>Basic form</h2>
{{= form}}
<h2>Submitted variables</h2>
{{= BEAUTIFY(request.vars)}}
ここでは示していませんが、Jinja2 や Django Template と同じようにテンプレートの派生を利用しています。Web2Py ではテンプレートと呼ばずビューとなることに留意してください。
SQLFORM
既存のデータベースへアクセスするときのフォーム作成が簡単になります。
まず、DALを使用してデータベースとの接続を確立した後、employeeというテーブルを作成したとします。
code: Python
db = DAL('sqlite://storage.sqlite')
db.define_table('employee', Field('name', requires = IS_NOT_EMPTY()))
コントローラは、次のコードでフォームを作成します-
code: Python
form = SQLFORM(
db.mytable,
record = mytable_index,
deletable = True,
submit_button = T('Update')
)
テーブルを変更するコントローラは次のようになります。
code: python
def display_form():
form = SQLFORM(db.person)
ビューに変更はありません。 新しいコントローラーでは、db.employeeテーブルから作成されたSQLFORMオブジェクトをモデルで定義するだけです。
from がビューに渡されて生成されるHTMLを見ると次のようになります。
code: HTML
<form enctype = "multipart/form-data" action = "" method = "post">
<table>
<tr id = "employee_name__row">
<td>
<label id = "person_name__label" for = "person_name">Your name: </label>
</td>
<td>
<input type = "text" class = "string" name = "name" value = "" id = "employee_name" />
</td>
<td></td>
</tr>
<tr id = "submit_record__row">
<td></td>
<td><input value = "Submit" type = "submit" /></td>
<td></td>
</tr>
</table>
<input value = "9038845529" type = "hidden" name = "_formkey" />
<input value = "employee" type = "hidden" name = "_formname" />
</form>
ビューを変更する必要はありませんが、コントローラーにはフォーム内のすべてのタグに、テーブルとフィールド名にアサインされている名前が必要になります。
code: Python
def display_form():
form = SQLFORM(db.employee)
if form.process().accepted:
response.flash = 'form accepted'
elif form.errors:
response.flash = 'form has errors'
else:
response.flash = 'please fill out the form'
return dict(form = form)
SQLFORMオブジェクトの、uploadフィールドではアップロードされたファイルをuploadsフォルダに自動的に保存します。
SQLFORMは textareasを使用して、チェックボックスおよびテキストの形式でブール値を表示することができます。
SQLFORMのprocess()メソッドに keepvalues=Trueを与えると、SQLFORMの値を保持することができます。
SQLFORM.factory
場合によってはデータベースにテーブルを定義せず、SQLFORM機能を利用したいだけというようなときもあります。こうしたときには、SQLFOPRM.factoryを使うと、既存のデータベースにテーブルがあるかのようにフォームを生成してくれます。
code: python
def form_from_factory():
form = SQLFORM.factory(
Field('your_name', requires = IS_NOT_EMPTY()),
Field('your_image', 'upload'))
if form.process().accepted:
response.flash = 'form accepted'
session.your_name = form.vars.your_name
session.your_image = form.vars.your_image
elif form.errors:
response.flash = 'form has errors'
return dict(form = form)
フォームはSQLFORMと同じように表示され、フィールドには名前と画像が含まれますが、データベースにテーブルを作成する必要がありません。
ビューとなる default/form_from_factory.html は次のようになります。
code: Python
{{extend 'layout.html'}}
{{= form}}
CRUDメソッド
CRUDはSQLFORM上で使用されるAPIです。 名前が示すようにフォームの作成、取得、更新、削除を行うことができます。データベースのテーブルを修正するようなときに使用します。
CRUDは、web2pyの他のAPIと違ってインポートする必要があります。
code: Python
from gluon.tools import Crud
crud = Crud(db)
table: CRUDメソッド
メソッド 機能
crud.tables() データベースで定義されているテーブルのリストを返します
crud.create(db.tablename) テーブルtablenameの作成フォームを返します
crud.read(db.tablename, id) テーブル名とレコードIDの読み取り専用フォームを返します
crud.delete(db.tablename, id) レコードを削除します
crud.select(db.tablename, query) テーブルから選択されたレコードのリストを返します
crud.search(db.tablename) 検索フォームのタプル(フォーム、レコード)を返します
crud() request.args() に基づいて上記のいずれかを返します
HTMLヘルパー
HTMLやXMLのタグを表現するための記述です。
HTMLでのタグ
A, ASSIGNJS, B, BEAUTIFY, BODY, BR, CAT, CENTER, CODE, COL, COLGROUP, DIV, EM,
EMBED, FIELDSET, FORM, H1, H2, H3, H4, H5, H6, HEAD, HR, HTML, I, IFRAME, IMG, INPUT,
LABEL, LEGEND, LI, LINK, MARKMIN, MENU, META, OBJECT, ON, OL, OPTGROUP, OPTION,
P, PRE, SCRIPT, SELECT, SPAN, STYLE, TABLE, TAG, TBODY, TD, TEXTAREA, TFOOT, TH,
THEAD, TITLE, TR, TT, UL, URL, XHTML, XML, embed64, xmlescape
具体的な例として次のビューを見てみましょう。
code: HTML
{{=DIV(B(I("hello ", "<world>")), _class="myclass")}}
これは、次のようにレンダリングされます。
code: HMTL
<div class="myclass"><b><i>hello <world></i></b></div>
データベース抽象化レイヤ
Web2Py ではデータベース抽象化レイヤ(DAL)によって、データベースが抽象化されます。
Djangoにも Django ORM (Object-Relational Mapping)と呼ばれる抽象化レイヤがありますが、これは非常に単純なことしか表現できません。 Web2Py の DAL はほとんどのSQLクエリを表現することができます。
また、DALは PyDAL として単独でも利用することができます。
Web2Py でSSL通信
SSL通信でリモートアクセスを許可するには、SSLを使用してWebフレームワークを起動させる必要があります。はじめに、リモートアクセスを許可するSSL証明書を作成します。
Linux系プラットフォームでは、opensslコマンドを使って、証明書の生成に使用するRSAキーを作成します。
code: bash
$ openssl genrsa -out server.key 2048
このキーを使用して、.csrファイルを生成します。
code: bash
$ openssl req -new -key server.key -out server.csr
最後に、この2つのファイル使用してSSL証明書を作成します。
code: bash
$ openssl x509 -req -days 365 \
-in server.csr -signkey server.key -out server.crt
これで、次のようにしてweb2py を起動するとSSL通信でアクセスさせることができます。
ただし、SSL証明書が既知の認証局によって署名されていないことを示す警告が表示されます。(いわゆるオレオレ認証です)
code: bash
$ python web2py.py -a 'admin_password' \
-c server.crt -k server.key -i 0.0.0.0 -p 8000
ブラウザからは、https://WEBサーバのIPアドレス:8000 でアクセスします。
外観の変更
CSSファイルを変更することでHTMLやコードを変えずに外観を変更することができます。
Web2Pyで定義したアプリケーション管理画面を下にスクロールしてStaticセクションのCSSをクリックします。すべてのCSSファイルとレイアウトファイルを表示します。 フォームの外観を変更するためには、これらのファイルを修正します。
https://gyazo.com/544c6e2cb05dcbc0973ec29615ad2b70
Py4Webの紹介
Web2Py と同じ Massimo Di Pierro 氏を中心として活発に開発されています。
Py4Wwbは、Webアプリケーションのフルスタック・フレームワークで、効率的なデータベース駆動型Webアプリケーションを迅速に開発することができます。web2pyの進化系ですが、内部設計がweb2pyに比べて大幅に簡素化されていて、はるかに高速(10〜20倍)で滑らかに動作します。 では、なぜPy4Webを取り上げずに、ベースとなった Web2Py を説明したのかというと、Py4Webはまた開発過程のプロジェクトでWeb2Py ほどには安定していないため、プロダクションレベルでの採用は難しと考えるからです。とはいえ個人プロジェクトではお勧めです。
https://gyazo.com/fd6e7a7ab947accd4722afa12e08f111
https://gyazo.com/efcadaa88d7418a133f48540b3ec0501
参考: